#include <algorithm>
#include <assert.h>

#include "wpsmvc.h"

#define ASSERT(x) assert(x)
#define FALSE 0
#define TRUE 1
extern int new_delete_moniter;

namespace
{
	template< class _Ty >
	class ks_castptr
	{
	private:
		_Ty* _ptr;

	public:
		ks_castptr()	{ _ptr = NULL; }
		ks_castptr(int nil) { ASSERT(nil == 0); _ptr = 0; }
		ks_castptr(_Ty* p) { _ptr = p; }
		ks_castptr(const ks_castptr<_Ty>& cp) { _ptr = (_Ty*)cp; }
		void clear()
		{
			_ptr = NULL;
		}
		template<class _Type>
		ks_castptr(_Type* p) 
		{
			_ptr = static_cast<_Ty*>(p);
			ASSERT(_check(p));
		}
		template<class _Type>
		ks_castptr(const ks_castptr<_Type>& p) 
		{
			_ptr = static_cast<_Ty*>((_Type*)p);
			ASSERT(_check((_Type*)p));
		}

		_Ty* operator=(int nil)
		{
			ASSERT(nil == 0);
			_ptr = 0;
			return _ptr;
		}

		_Ty* operator=(const ks_castptr<_Ty>& cp)
		{
			_ptr = (_Ty*)cp;
			return _ptr;
		}

		template<class _Type>
		_Ty* operator=(_Type* p)
		{
			_ptr = static_cast<_Ty*>(p);
			ASSERT(_check(p));
			return _ptr;
		}
		template<class _Type>
		_Ty* operator=(const ks_castptr<_Type>& sp)
		{
			_ptr = static_cast<_Ty*>((_Type*)sp);
			ASSERT(_check((_Type*)sp));
			return _ptr;
		}

		bool operator==(_Ty* p) const {	return _ptr == p;	}
		bool operator!=(_Ty* p) const {	return _ptr != p;	}
		bool operator!() const	{ return _ptr == NULL; }
		_Ty& operator*() const	{ return *_ptr; }
		_Ty* get() const        { return _ptr; }
		operator _Ty*() const	{ return _ptr; }
		_Ty** operator&() { return &_ptr; }
		_Ty* operator->() const { return _ptr; }

	private:
		template<class _Type>
		bool _check(_Type* p)
		{
#ifdef _DEBUG
			if (!p)
				return true;
			_Ty* pd = dynamic_cast<_Ty*>(p);
			return (pd && pd == _ptr);
#endif 
			return true;
		}
	};

}

AbstractContext::~AbstractContext()
{

}

AbstractObject::AbstractObject()
{
	new_delete_moniter++;
	m_parent = NULL;
}

AbstractObject::~AbstractObject()
{
	new_delete_moniter--;
}

void AbstractObject::destory()
{
	if (m_parent)
		m_parent->removeChild(this);
	while (m_children.size() > 0)
		(*m_children.begin())->destory();
	m_children.clear();
	delete this;
}

void AbstractObject::addChild( AbstractObject* child )
{
	ASSERT(child);
	child->m_parent = this;
	m_children.push_back(child);
}

void AbstractObject::removeChild( AbstractObject* child )
{
	auto it = std::find(m_children.begin(), m_children.end(), child);
	if (it != m_children.end())
		m_children.erase(it);
}

AbstractObject* AbstractObject::getChildObject( int index )
{
	ASSERT(index >= 0 && index < (int)m_children.size());
	return m_children[index];
}

int AbstractObject::getChildCount()
{
	return m_children.size();
}

void AbstractObject::insertChild( int index, AbstractObject* child )
{
	m_children.insert(m_children.begin() + index, child);
}

AbstractModel::AbstractModel()
{
	m_layer = NULL;
}

AbstractModel::~AbstractModel()
{

}

AbstractVisual* AbstractModel::createVisual( AbstractContext* context )
{
	ks_castptr<AbstractLayerVisual> layerVisual = m_layer->getVisual(context);
	AbstractVisualFactory* factory = layerVisual->getVisualFactory();
	return factory->createNormalVisual(this, context);
}

AbstractVisual* AbstractModel::getVisual( AbstractContext* context )
{
	auto it = m_visuals.find(context->getLayoutId());
	if (it != m_visuals.end())
		return it->second;
	AbstractVisual* visual = createVisual(context);
	addVisual(context, visual);
	if (AbstractModel* parent = getParent())
	{
		AbstractVisual* visualOfParent = parent->getVisual(context);
		visualOfParent->addSubVisual(visual);
	}
	return visual;
}

void AbstractModel::addVisual( AbstractContext* context, AbstractVisual* visual )
{
	ASSERT(m_visuals.find(context->getLayoutId()) == m_visuals.end());
	m_visuals[context->getLayoutId()] = visual;
	visual->m_model = this;
	visual->m_context = context;
	visual->m_layer = m_layer->getVisual(context);
}

void AbstractModel::removeVisual( AbstractContext* context, AbstractVisual* visual )
{
	auto it = m_visuals.find(context->getLayoutId());
	if (it != m_visuals.end())
		m_visuals.erase(it);
}

int AbstractModel::getVisualCount()
{
	return m_visuals.size();
}

void AbstractModel::destory()
{
	if (getParent())
		getParent()->removeChild(this);
	while (m_children.size() > 0)
		(*m_children.begin())->destory();
	while (m_visuals.size() > 0)
		(m_visuals.begin()->second)->destory();
	m_children.clear();
	m_visuals.clear();
	delete this;
}

void AbstractModel::addChild( AbstractObject* c )
{
	ks_castptr<AbstractModel> child = c;
	if (child->m_layer == NULL)
		child->m_layer = m_layer;
	ClassBase::addChild(child);
}

AbstractModel* AbstractModel::getChild( int index )
{
	return ks_castptr<AbstractModel>(ClassBase::getChildObject(index));
}

AbstractModel* AbstractModel::getParent()
{
	return ks_castptr<AbstractModel>(m_parent);
}

AbstractVisual::AbstractVisual()
{
	m_model = NULL;
	m_layer = NULL;
	m_supVisual = NULL;
	m_context = NULL;
}

AbstractVisual::~AbstractVisual()
{

}

void AbstractVisual::destory()
{
	if (m_model)
		m_model->removeVisual(m_context, this);
	if (m_supVisual)
		m_supVisual->removeSubVisual(this);
	while (m_subVisuals.size() > 0)
		(*m_subVisuals.begin())->destory();
	ClassBase::destory();
}

AbstractModel* AbstractVisual::getModel()
{
	return m_model;
}

AbstractVisual* AbstractVisual::getSubVisual(int index)
{
	ASSERT(index >= 0 && index < (int)m_subVisuals.size());
	return m_subVisuals[index];
}

AbstractVisual* AbstractVisual::getSupVisual()
{
	return m_supVisual;
}

int AbstractVisual::getSubVisualCount()
{
	return m_subVisuals.size();
}

void AbstractVisual::addSubVisual( AbstractVisual* subVisual )
{
	if (subVisual->m_supVisual)
		subVisual->m_supVisual->removeSubVisual(subVisual);
	subVisual->m_supVisual = this;
	m_subVisuals.push_back(subVisual);
}

void AbstractVisual::removeSubVisual( AbstractVisual* subVisual )
{
	auto it = std::find(m_subVisuals.begin(), m_subVisuals.end(), subVisual);
	if (it != m_subVisuals.end())
		m_subVisuals.erase(it);
}

void AbstractVisual::insertSubVisual( int index, AbstractVisual* subVisual )
{
	m_subVisuals.insert(m_subVisuals.begin() + index, subVisual);
}

void AbstractVisual::addChild( AbstractObject* c )
{
	ks_castptr<AbstractVisual> child = c;
	if (child->m_layer == NULL)
		child->m_layer = m_layer;
	ClassBase::addChild(child);
	addSubVisual(child);
}

AbstractVisual* AbstractVisual::getChild( int index )
{
	return ks_castptr<AbstractVisual>(ClassBase::getChildObject(index));
}

void AbstractLayer::addChild( AbstractObject* c )
{
	ks_castptr<AbstractModel> child = c;
	ASSERT(child->m_layer == NULL);
	child->m_layer = this;
	ClassBase::addChild(child);
}

AbstractVisual* AbstractLayer::createVisual( AbstractContext* context )
{
	ks_castptr<AbstractLayerVisual> layerVisual = m_layer->getVisual(context);
	AbstractVisualFactory* factory = layerVisual->getVisualFactory();
	return factory->createLayerVisual(this, context);
}

Cellection* AbstractLayer::getCellection( AbstractContext* context )
{
	auto it = m_cellections.find(context->getViewId());
	if (it != m_cellections.end())
		return it->second;
	return NULL;
}

AbstractVisualFactory::~AbstractVisualFactory()
{

}
